/*
 * QApplicationAdapter.cpp  0.4.0 / Nov 17, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#include "QApplicationAdapter.h"

#include "ComponentDelegate.h"
#include "QCursorAdapter.h"

// QApplicationAdapter :: Public Constructor. ----------------------------------

/*!
 * \brief Constructs new QApplicationAdapter object.
 *
 * \param argc the number of command line arguments
 * \param argv the command line arguments
 */
QApplicationAdapter::QApplicationAdapter(int &argc, char **argv)
  : QApplication(argc, argv), m_fontSet(0)
{
  setWindowIcon(QIcon(":/Cute4jLogo16x16.png"));
  connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuitSlot()));
  connect(this, SIGNAL(aboutCute4jSignal(const QString &, const QString &)),
          this, SLOT(aboutCute4jSlot(const QString &, const QString &)),
          Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(aboutQtSignal()), this, SLOT(aboutQt()),
          Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(setTranslationSignal(bool *, const QString &)), this,
          SLOT(setTranslationSlot(bool *, const QString &)),
          Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(removeTranslationSignal()), this,
          SLOT(removeTranslationSlot()), Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(setStyleSheetSignal(const QString &)), this,
          SLOT(setStyleSheetSlot(const QString &)),
          Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(setOverrideCursorSignal(jint)), this,
          SLOT(setOverrideCursorSlot(jint)), Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(changeOverrideCursorSignal(jint)), this,
          SLOT(changeOverrideCursorSlot(jint)), Qt::BlockingQueuedConnection);
  connect(this, SIGNAL(restoreOverrideCursorSignal()), this,
          SLOT(restoreOverrideCursorSlot()), Qt::BlockingQueuedConnection);
}

// QApplicationAdapter :: Public Member Function. ------------------------------

/*!
 * \brief Displays information about Cute4j.
 *
 * \param env the JNIEnv pointer
 * \param version the version of the library
 * \param date the release date
 */
void QApplicationAdapter::aboutCute4j(JNIEnv *env, jstring version,
                                      jstring date)
{
  QStringAdapter versionText(env, version);
  QStringAdapter versionDate(env, date);
  if (JNISwingWrapper::isSwingThread(env)) {
    aboutCute4jSlot(versionText, versionDate);
  } else {
    emit aboutCute4jSignal(versionText, versionDate);
  }
}

/*!
 * \brief Displays about Qt message box.
 *
 * \param env the JNIEnv pointer
 */
void QApplicationAdapter::aboutQt(JNIEnv *env)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    QApplication::aboutQt();
  } else {
    emit aboutQtSignal();
  }
}

/*!
 * \brief Sets translation.
 *
 * \param env the JNIEnv pointer
 * \param fileName the translation file name
 *
 * \return \c true if succeed
 */
bool QApplicationAdapter::setTranslation(JNIEnv *env, const QString &fileName)
{
  bool succeed;
  if (JNISwingWrapper::isSwingThread(env)) {
    setTranslationSlot(&succeed, fileName);
  } else {
    emit setTranslationSignal(&succeed, fileName);
  }
  return succeed;
}

/*!
 * \brief Removes translation.
 *
 * \param env the JNIEnv pointer
 */
void QApplicationAdapter::removeTranslation(JNIEnv *env)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    removeTranslationSlot();
  } else {
    emit removeTranslationSignal();
  }
}

/*!
 * \brief Sets style sheet.
 *
 * \param env the JNIEnv pointer
 * \param styleSheetText the style sheet text
 */
void QApplicationAdapter::setStyleSheet(JNIEnv *env, jstring styleSheetText)
{
  QStringAdapter styleSheet(env, styleSheetText);
  if (JNISwingWrapper::isSwingThread(env)) {
    setStyleSheetSlot(styleSheet);
  } else {
    emit setStyleSheetSignal(styleSheet);
  }
}

/*!
 * \brief Sets application override cursor.
 *
 * \param env the JNIEnv pointer 
 * \param type the style cursor type
 */
void QApplicationAdapter::setOverrideCursor(JNIEnv *env, jint type)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    setOverrideCursorSlot(type);
  } else {
    emit setOverrideCursorSignal(type);
  }
}

/*!
 * \brief Changes application override cursor.
 *
 * \param env the JNIEnv pointer
 * \param type the style cursor type
 */
void QApplicationAdapter::changeOverrideCursor(JNIEnv *env, jint type)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    changeOverrideCursorSlot(type);
  } else {
    emit changeOverrideCursorSignal(type);
  }
}

/*!
 * \brief Undos last setOverrideCursor().
 *
 * \param env the JNIEnv pointer
 */
void QApplicationAdapter::restoreOverrideCursor(JNIEnv *env)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    restoreOverrideCursorSlot();
  } else {
    emit restoreOverrideCursorSignal();
  }
}

/*!
 * \brief Sets font set.
 *
 * \param fontSet the font set
 */
void QApplicationAdapter::setFontSet(QFontSet *fontSet)
{
  // TODO: check who delets m_fontSetn - remove if not used
  if (fontSet != m_fontSet) {
    setFont(fontSet->defaultFont());
    setFont(fontSet->fixedFont(), "QTextArea");
    setFont(fontSet->componentFont(), "QWidget");
    QFont buttonFont = fontSet->buttonFont();
    setFont(buttonFont, "QAbstractButton");
    setFont(buttonFont, "QCheckBox");
    setFont(buttonFont, "QPushButton");
    setFont(buttonFont, "QRadioButton");
    setFont(buttonFont, "QToolButton");
    setFont(fontSet->menuFont(), "QMenu");
    setFont(fontSet->menuBarFont(), "QMenuBar");
    setFont(fontSet->textFont(), "QLabel");
    setFont(fontSet->toolTipFont(), "QTipLabel");
    m_fontSet = fontSet;
  }
}

// QApplicationAdapter :: Public Static Member Function. -----------------------

/*!
 * \brief Quits main loop.
 *
 * \return loop exit code
 */
int QApplicationAdapter::exec()
{
  return QApplication::exec();
}

// QApplicationAdapter :: Private Member Functions. ----------------------------

void QApplicationAdapter::aboutCute4jSlot(const QString &version,
                                          const QString &date)
{
  QMessageBox mb(QApplication::activeWindow());
  mb.setWindowTitle(translate("Cute4j", "About Cute4j"));
  mb.setText(QString(
    "<h3>Cute4j</h3>"
    "<p>Version: %1 / %2.</p>"
    "<p><a href=\"http://www.cute4j.com/\">Cute4j</a> is a set of "
    "<a href=\"http://qt.nokia.com\">Qt</a> libraries packed for Java "
    "developers. "
    "<p>The library is published under the LGPL version 2.1 license.<br/>"
    "Copyright (c) 2010 - 2011, "
    "<a href=\"http://www.cute4j.com/\">cute4j.com</a> and contributors.</p>").
    arg(version).arg(date));
  mb.setIconPixmap(QPixmap(":/Cute4jLogo32x32.png"));
  mb.addButton(QMessageBox::Ok);
  mb.exec();
}

void QApplicationAdapter::setTranslationSlot(bool *succeed,
                                             const QString &fileName)
{
  if (sm_translator) {
    removeTranslator(sm_translator);
    delete sm_translator;
  }
  sm_translator = new QTranslator();
  if (sm_translator->load(fileName)) {
    installTranslator(sm_translator);
    *succeed = true;
  } else {
    delete sm_translator;
    sm_translator = 0;
    *succeed = false;
  }
}

void QApplicationAdapter::removeTranslationSlot()
{
  if (sm_translator) {
    removeTranslator(sm_translator);
    delete sm_translator;
    sm_translator = 0;
  }
}

void QApplicationAdapter::setStyleSheetSlot(const QString &styleSheetText)
{
  bool removed = styleSheetText.isEmpty();
  QApplication::setStyleSheet(styleSheetText);
  QWidgetList widgetList = topLevelWidgets();
  for (int i = widgetList.size(); --i >= 0;) {
    QWidget *widget = widgetList[i]; // TODO: not necessary ?
    ComponentDelegate *componentDelegate =
                            qObjectDelegatePointer<ComponentDelegate *>(widget);
    if (componentDelegate) {
      componentDelegate->styleSheetChanged(removed);
    }
  }
}

void QApplicationAdapter::setOverrideCursorSlot(jint type)
{
  QApplication::setOverrideCursor(QCursorAdapter(type));
}

void QApplicationAdapter::changeOverrideCursorSlot(jint type)
{
  QApplication::changeOverrideCursor(QCursorAdapter(type));
}

void QApplicationAdapter::restoreOverrideCursorSlot()
{
  QApplication::restoreOverrideCursor();
}

void QApplicationAdapter::aboutToQuitSlot()
{
  QWidgetList allWidgetsList = allWidgets();
  QWidgetList topLevelWidgetsList;
  const int allWidgetsListSize = allWidgetsList.size();
  for (int i = 0; i < allWidgetsListSize; i++) {
    QWidget *widget = allWidgetsList.at(i);
    if (widget->isWindow() && !widget->parent() &&
        widget->property(QObjectDelegate::DELEGATE_PROPERTY_NAME).isValid()) {
      topLevelWidgetsList.append(widget);
    }
  }
  for (int i = topLevelWidgetsList.size(); --i >= 0;) {
    delete topLevelWidgetsList.at(i);
  }
}

// QApplicationAdapter :: Private Static Data Member. --------------------------

QTranslator *QApplicationAdapter::sm_translator = 0;
